package com.j.lemon.learn.thread.demo;

import java.util.concurrent.*;

/**
 * @Author lijunjun
 * @Date 2019-03-25 16:46
 * @Description 本demo将demo1中的hashMap改为ConcurrentHashMap，解决了加锁效率低下的问题，但却引发了另外一个问题：有很大的可能会重复计算，两个线程都判断缓存中没有，
 *              都会进行计算，如果这个计算非常耗时，就得不偿失了。
 */
public class Demo2<A, V> {
    private static final CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(10000);
    private final ConcurrentHashMap<A, V> map = new ConcurrentHashMap<>();
    private Computable<A, V> c;

    private Demo2(Computable<A, V> c) {
        this.c = c;
    }

    public V compute(A a) {
        V v = map.get(a);
        if (v == null) {
            v = c.compute(a);
            map.put(a, v);
        }
        return v;
    }

    private static class TestThread<A,V> implements Runnable{
        private Demo2<A,V> demo1;
        private A k;
        TestThread(Demo2<A,V> demo1, A k) {
            this.demo1=demo1;
            this.k=k;
        }

        @Override
        public void run() {
            demo1.compute(k);
            COUNT_DOWN_LATCH.countDown();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(8, 16, 0, TimeUnit.MILLISECONDS,
                new LinkedBlockingDeque<>(), r -> new Thread(r,"lala"),new ThreadPoolExecutor.DiscardPolicy());

        Demo2<String,Integer> demo1 = new Demo2<>(new ComputableImpl());
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            threadPoolExecutor.execute(new TestThread<>(demo1,"888"));
        }
        COUNT_DOWN_LATCH.await();
        long end = System.currentTimeMillis();

        System.out.println(end-start);
        threadPoolExecutor.shutdown();







    }
}
